package cn.iocoder.yudao.module.scrm.service.marketing.operation;

import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.scrm.controller.admin.marketing.vo.operation.*;
import cn.iocoder.yudao.module.scrm.dal.dataobject.marketing.MarketingContentDO;
import cn.iocoder.yudao.module.scrm.dal.dataobject.marketing.MarketingLookDO;
import cn.iocoder.yudao.module.scrm.dal.dataobject.marketing.MarketingTransmitDO;
import cn.iocoder.yudao.module.scrm.dal.dataobject.marketing.MarketingVisitorDO;
import cn.iocoder.yudao.module.scrm.dal.mysql.marketing.MarketingContentMapper;
import cn.iocoder.yudao.module.scrm.dal.mysql.marketing.MarketingLookMapper;
import cn.iocoder.yudao.module.scrm.dal.mysql.marketing.MarketingTransmitMapper;
import cn.iocoder.yudao.module.scrm.dal.mysql.marketing.MarketingVisitorMapper;
import cn.iocoder.yudao.module.scrm.service.marketing.transmit.MarketingTransmitService;
import cn.iocoder.yudao.module.scrm.util.DateToUtil;
import cn.iocoder.yudao.module.system.api.cp.RadarApi;
import cn.iocoder.yudao.module.system.api.cp.dto.RadarSaveReqVO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.scrm.enums.ErrorCodeConstants.*;

/**
 * 营销操作 Service 实现类
 * @Author LiZhiMin
 * @Date 2024/8/10 10:29
 */
@Service
@Validated
public class MarketingOperationServiceImpl implements MarketingOperationService{

    private static final ExecutorService executorService = Executors.newFixedThreadPool(10); // 创建一个固定大小的线程池

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private MarketingContentMapper contentMapper;

    @Resource
    private MarketingTransmitMapper transmitMapper;

    @Resource
    private MarketingVisitorMapper visitorMapper;

    @Resource
    private MarketingLookMapper lookMapper;

    @Resource
    private RadarApi radarApi;

    @Resource
    private SocialClientApi socialClientApi;

    @Resource
    private MarketingTransmitService marketingTransmitService;





    /**
     * 员工|访客-转发营销内容-进行记录转发次数和数据
     * @param vo 入参
     * @return 返回
     */
    @Override
    public TransmitRespVO transmit(TransmitReqVO vo) {
        if ("0".equals(vo.getSource())){
            return transmitByEmployee(vo);
        }
        //访客进行转发
        return null;

    }

    /**
     * 员工|访客-访问营销内容进行记录浏览数据
     *
     *
     * @param vo 入参
     * @return 返回
     */
    @Override
    public VisitorRespVO visitor(Integer tenantId,VisitorReqVO vo) {
        return visitorByEmployee(tenantId,vo);
    }

    /**
     * 发送访问雷达信息
     * @param vo 入参
     * @return 返回
     */
    @Override
    public Boolean sendMessage(Integer tenantId ,SendMessageVo vo) {
        //根据link获取标题|要转发的人
        RadarSaveReqVO radarSaveReqVO = BeanUtils.toBean(vo, RadarSaveReqVO.class);
        MarketingTransmitDO transmitDO = transmitMapper.selectOne(MarketingTransmitDO::getLinkId, vo.getLinkId());
        if (transmitDO==null){
            throw exception(MARKETING_CONTENT_SHARE_ONE);
        }
        MarketingContentDO  contentDO = contentMapper.selectById( transmitDO.getContentId());//TODO 小黎 解决空指针报错问题
        if (contentDO==null){
            throw exception(MARKETING_CONTENT_SHARE_TWO);
        }
        radarSaveReqVO.setTitle(contentDO.getTitle());
        radarSaveReqVO.setToUser(transmitDO.getWxUserId());
        radarSaveReqVO.setTenantId(tenantId);
        //String url = String.format("http://47.115.144.28:7001/pagesB/pages/marketingdetails/marketingdetails?id=%d&marketingType=%d&tenantid=%d", contentDO.getId(), contentDO.getMarketingType(), tenantId);
       //radarSaveReqVO.setPageUrl(url);
        return radarApi.sendRadarMessage(radarSaveReqVO).getCheckedData();
    }


    /**
     * 用户授权后获取微信用户的信息根据code
     * @param tenantId 租户
     * @param vo 入参
     * @return 用户西悉尼
     */
    @Override
    public WxInfoRespVo getWeChatInfoByCode(Integer tenantId, WxAuthorizerReqVo vo) {
        //根据code获取加密秘钥
       /* String appId = configService.getValue(Constant.WX_APP_ID);
        String appSecret = configService.getValue(Constant.WX_APP_Secret);
        JSONObject json = WechatUtil.getSessionKeyOropenid(param.getCode(),appId,appSecret);
        String session_key = json.getString("session_key");
        String openid = json.get("openid").toString();
        return R.ok().put("session_key",session_key).put("openid",openid);*/

        return null;
    }

    /**
     * getWxPhone
     * @param userType 用户类型
     * @param phoneCode 前端获取的手机code
     * @return 返回
     */
    @Override
    public SocialWxPhoneNumberInfoRespDTO getWxPhone(Integer userType, String phoneCode) {

        return socialClientApi.getWxMaPhoneNumberInfoNotToken(userType,phoneCode).getCheckedData();
    }


    /**
     * 获取转发表信息
     */
    private MarketingTransmitDO getTransmitDO(String linkId) {
        return transmitMapper.selectOne(MarketingTransmitDO::getLinkId, linkId);
    }

    /**
     * 获取内容信息
     */
    private MarketingContentDO getContentDO(String contentId) {
        return contentMapper.selectOne(MarketingContentDO::getId, contentId);
    }

    /**
     * 获取访客信息
     */
    private MarketingVisitorDO getVisitorDO(String linkId, String phone) {
        QueryWrapper<MarketingVisitorDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("link_id", linkId).eq("phone", phone);
        return visitorMapper.selectOne(queryWrapper);
    }

    /**
     * 添加新访客并返回其ID
     */
    private String addNewVisitor(VisitorReqVO vo, String contentId, String transmitId, LocalDateTime endLookTime,
                                 String principalName,String source,
                                 String weChatAvatar,String name,String phone,String userId) {
        MarketingVisitorDO visitorInsertDo = BeanUtils.toBean(vo, MarketingVisitorDO.class);
        visitorInsertDo.setContentId(contentId)
                .setTransmitId(transmitId)
                .setEndLookTime(endLookTime)
                .setAllLookCount(1)
                .setAllLookTime(vo.getLookTime())
                .setPrincipalName(principalName)
                .setSource(source)
                .setWeChatAvatar(weChatAvatar)
                .setName(name)
                .setPhone(phone)
                .setCreator(userId);//谁转发的谁就是负责人
        visitorMapper.insert(visitorInsertDo);
        return String.valueOf(visitorInsertDo.getId());
    }

    /**
     * 插入营销浏览记录
     */
    private void insertMarketingLookRecord(VisitorReqVO vo, String contentId, String visitorId, String title, String principalName, String transmitId,String source,String userId) {
        MarketingLookDO lookInsertDo = BeanUtils.toBean(vo, MarketingLookDO.class);
        lookInsertDo.setContentId(contentId)
                .setVisitorId(visitorId)
                .setTitle(title)
                .setPrincipalName(principalName)
                .setTransmitId(transmitId)
                .setSource(source)
                .setCreator(userId);
        lookMapper.insert(lookInsertDo);
    }

    /**
     * 更新转发统计信息
     */
    private void updateTransmitStats(MarketingTransmitDO transmitDO) {
        int newBrowseCount = (transmitDO.getBrowseCount() == null) ? 1 : transmitDO.getBrowseCount() + 1;
        int newGainCustomerCount = (transmitDO.getGainCustomerCount() == null) ? 1 : transmitDO.getGainCustomerCount() + 1;
        transmitMapper.updateById(transmitDO.setBrowseCount(newBrowseCount).setGainCustomerCount(newGainCustomerCount));
    }



    /**
     * 2-增加转发表的浏览次数
     */
    private void incrementBrowseCount(MarketingTransmitDO transmitDO) {
        transmitDO.setBrowseCount(transmitDO.getBrowseCount() + 1);
        transmitMapper.updateById(transmitDO);
    }

    /**
     * 更新访客数据
     */
    private void updateVisitorData(MarketingVisitorDO visitorDO, LocalDateTime endLookTime, int lookTime) {
        visitorDO.setEndLookTime(endLookTime)
                .setAllLookCount(visitorDO.getAllLookCount() + 1)
                .setAllLookTime(visitorDO.getAllLookTime() + lookTime);
        visitorMapper.updateById(visitorDO);
    }

    /**
     * 插入营销浏览记录
     */
    private void insertMarketingLookRecord(VisitorReqVO vo, String contentId, String title, String principalName, String transmitId, Integer visitorId,String source,String userId) {
        MarketingLookDO lookInsertDo = BeanUtils.toBean(vo, MarketingLookDO.class);
        lookInsertDo.setContentId(contentId)
                .setVisitorId(String.valueOf(visitorId))
                .setTitle(title)
                .setPrincipalName(principalName)
                .setTransmitId(transmitId)
                .setSource(source)
                .setCreator(userId);
        lookMapper.insert(lookInsertDo);
    }





    /**
     * 员工转发营销内容-进行记录转发次数和数据
     * 当前登陆员工
     *      第一次进行转发就在转发表中生成一条记录，分享次数初始化为1  浏览人数初始化为0   获客人数为0
     *
     *      第 n 次进行转发就在转发表中  分享次数加1
     * @param vo 入参
     * @return 返回
     *
     *
     */
    public TransmitRespVO transmitByEmployee(TransmitReqVO vo) {
        AdminUserRespDTO userInfo = adminUserApi.getUserNotCheckDataPermission(getLoginUserId()).getCheckedData();
        DeptRespDTO deptInfo = deptApi.getDeptNotCheckDataPermission(userInfo.getDeptId()).getCheckedData();

        QueryWrapper<MarketingTransmitDO> queryWrapper = new QueryWrapper<>();
        Long tenantId = TenantContextHolder.getTenantId();
        queryWrapper.eq("user_id", userInfo.getId())
                .eq("wx_user_id", userInfo.getWxUserId())
                .eq("content_id", vo.getContentId())
                .eq("tenant_id", tenantId);

        //判断当前登陆人是否转发过这篇文章
        MarketingTransmitDO transmitDO = transmitMapper.selectOne(queryWrapper);

        //第一次转发初始化数据
        MarketingTransmitDO transmitInsertDo = BeanUtils.toBean(vo, MarketingTransmitDO.class);
        transmitInsertDo.setShareCount(0);
        transmitInsertDo.setBrowseCount(0);
        transmitInsertDo.setGainCustomerCount(0);
        transmitInsertDo.setUserId(Optional.of(userInfo)
                .map(users -> Long.valueOf(users.getId().toString()))
                .orElse(null));
        transmitInsertDo.setWxUserId(Optional.of(userInfo).map(AdminUserRespDTO::getWxUserId).orElse(null));
        transmitInsertDo.setName(Optional.of(userInfo).map(AdminUserRespDTO::getNickname).orElse(null));
        transmitInsertDo.setDept(Optional.ofNullable(deptInfo).map(DeptRespDTO::getName).orElse(null));
        transmitInsertDo.setLinkId(String.valueOf(UUID.randomUUID()));

        if ("0".equals(vo.getType()) && transmitDO == null) {//获取唯一linkId 转发次数为0
            //没有转发过就在转发表中插入一次记录
            transmitMapper.insert(transmitInsertDo);
        } else if ("1".equals(vo.getType()) && transmitDO != null) {//转发操作
            //转发过就转发次数加一
            transmitDO.setShareCount(transmitDO.getShareCount() + 1);
            transmitMapper.updateById(transmitDO);
        }

        return BeanUtils.toBean(transmitDO != null ? transmitDO : transmitInsertDo, TransmitRespVO.class);
    }




    /**
     * 对员工转发的内容进行访问  记录访问数据
     * 访客  张三第一次进行访问，访问数据表    新增一条数据 昵称，手机号，转发的链路id，并且初始化：累计访问次数为1 ，累计访问时间为传入的访问时长，最后访问时间为结束时间
     *                      营销浏览记录表 插入一条记录，开始时间，结束时间，负责人，标题
     *                      转发表中的  浏览人数和获客人数 都加1
     *
     * 访客  张三第 n 次进行访问  访问数据表中  修改最后访问时间，  累计访问次数加1    累计时长：上次访问时长加上这次访问时长
     *                           营销浏览记录表 插入一条记录，开始时间，结束时间，负责人，标题
     *                          转发表    结束时间与上次的最后访问时间不是同一天就增加转发表中的一次浏览人数
     * @param vo 入参
     * @return 返回
     */
    public VisitorRespVO visitorByEmployee(Integer tenantId,VisitorReqVO vo) {
        String linkId = vo.getLinkId();
        LocalDateTime endLookTime = vo.getEndTime();
        //String openId = vo.getOpenId();
        String name = vo.getName();
        String weChatAvatar = vo.getWeChatAvatar();
        String phone = vo.getPhone();

        // 查询转发和内容表信息
        MarketingTransmitDO transmitDO = getTransmitDO(linkId);
        if (transmitDO==null){
            throw exception(MARKETING_CONTENT_SHARE_THREE);
        }
        MarketingContentDO contentDO = getContentDO(transmitDO.getContentId());
        if (contentDO==null){
            throw exception(MARKETING_CONTENT_SHARE_FOUR);
        }
        // 提取转发表和内容表信息
        String title = contentDO.getTitle();
        String principalName = transmitDO.getName();
        String transmitId = transmitDO.getId().toString();
        String contentId = transmitDO.getContentId();
        String source = transmitDO.getSource();
        String userId = String.valueOf(transmitDO.getUserId());//转发负责人id

        // 查询访客信息
        MarketingVisitorDO visitorDO = getVisitorDO(linkId, phone);

        if (visitorDO == null) {
            // 新访客处理
            String visitorId = addNewVisitor(vo, contentId, transmitId, endLookTime, principalName,source,weChatAvatar,name,phone,userId);

            // 插入营销浏览记录
            insertMarketingLookRecord(vo, contentId, visitorId, title, principalName, transmitId,source,userId);

            // 更新转发统计信息
            updateTransmitStats(transmitDO);


        }else {
            Date endLookDate = DateToUtil.localDateTimeToDateInZone(endLookTime, "Asia/Shanghai");
            Date lastVisitDate = DateToUtil.localDateTimeToDateInZone(visitorDO.getEndLookTime(), "Asia/Shanghai");

            //判断某人今天是否第一次访问这篇文章
            boolean isSameDay = DateUtil.isSameDay(lastVisitDate, endLookDate);

            if (!isSameDay) {//某人第n次访问增加一次转发表中的浏览次数
                incrementBrowseCount(transmitDO);
            }
            //更新访客数据
            updateVisitorData(visitorDO, endLookTime, vo.getLookTime());

            //插入营销浏览记录
            insertMarketingLookRecord(vo, contentId, title, principalName, transmitId, visitorDO.getId(),source,userId);


        }
        //发送浏览完成的雷达消息给-文章转发人
        SendMessageVo messageVo = new SendMessageVo();
        messageVo.setName(name);
        messageVo.setLinkId(linkId);
        messageVo.setRadarType("2");

        // 使用三元表达式进行 null 判断并设置字段值
        messageVo.setLookTime(vo.getLookTime() != null ? vo.getLookTime() : messageVo.getLookTime());
        messageVo.setPercentage(vo.getPercentage() != null ? vo.getPercentage() : messageVo.getPercentage());
        sendMessage(tenantId,messageVo);

        return new VisitorRespVO();
    }



}
